/*
 * ByteUtil.java        1.0     2009-6-30  15:16:07
 */
package com.microwintech.boardingtreasure.util;

import java.io.ByteArrayOutputStream;

/**
 * Created by IntelliJ IDEA. User: Chris.F Date: 2009-6-30 Time: 15:16:07
 */
public final class ByteUtil {
	public static String bytesToHex(byte[] b) {
		StringBuffer buf = new StringBuffer("");
		for (byte aB : b)
			buf.append(byteToHex(aB));
		return buf.toString();
	}

	public static byte[] hexToBytes(String hex) {
		int length = hex.length();
		if (length % 2 != 0)
			throw new IllegalArgumentException("illegal hex string size");
		ByteArrayOutputStream bos = new ByteArrayOutputStream(length / 2);
		for (int i = 0; i < length; i += 2) {
			char[] hex_digit = new char[2];
			hex_digit[0] = hex.charAt(i);
			hex_digit[1] = hex.charAt(i + 1);
			byte b = 0;
			for (char a : hex_digit) {
				int n;
				if (a >= 48 && a <= 57)
					n = a - 48; // 0-9
				else if (a >= 65 && a <= 70)
					n = a - 55; // A-F
				else if (a >= 97 && a <= 102)
					n = a - 87; // a-f
				else
					throw new IllegalArgumentException("illegal charactor: " + a);
				b = (byte) (b << 4);
				b = (byte) (b | (n & 0xff));
			}
			bos.write(b);
		}
		return bos.toByteArray();
	}

	public static String byteToHex(byte b) {
		// Returns hex String representation of byte b
		char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
		return new String(array);
	}

	public static long b2iu(byte b) {
		return b < 0 ? b & 0x7F + 128 : b;
	}

	public static byte[] concat(byte[]... args) {
		int length = 0;
		for (byte[] arg : args) {
			length += arg.length;
		}
		return concat(length, args);
	}

	public static byte[] concat(int length, byte[]... args) {
		byte[] result = new byte[length];
		int pos = 0;
		for (byte[] arg : args) {
			if (arg.length == 0)
				continue;
			int copylength = arg.length;
			System.arraycopy(arg, 0, result, pos, copylength);
			pos += copylength;
		}
		return result;
	}

	// The bitwise exclusive-OR of two bit strings X and Y of the same length
	public static byte[] XOR(byte[] arg1, byte[] arg2) {
		assert arg1.length == arg2.length;
		byte[] result = new byte[arg1.length];
		for (int i = 0; i < result.length; i++) {
			result[i] = (byte) (arg1[i] ^ arg2[i]);
		}
		return result;
	}

	// return highest (left-most) len bytes of source
	public static byte[] MSB(byte[] source, int len) {
		byte[] result = new byte[len];
		System.arraycopy(source, 0, result, 0, len);
		return result;
	}

	// return lowest (right-most) len bytes of source
	public static byte[] LSB(byte[] source, int len) {
		byte[] result = new byte[len];
		System.arraycopy(source, source.length - len, result, 0, len);
		return result;
	}

	public static byte[] convertNumToBytes(Number number, int byteNumber) {
		byte[] result = new byte[byteNumber];
		long temp = number.longValue();
		for (int i = byteNumber; i > 0; i--) {
			result[i - 1] = (byte) temp;
			temp = temp >> 8;
		}
		return result;
	}

	public static Number convertBytesToNum(byte[] number) {
		long result = 0;
		for (byte aNumber : number) {
			result = result << 8;
			result = result | (aNumber & 0xff);
		}
		return result;
	}

	public static byte[] sub(byte[] source, int begin) {
		if (source == null)
			return null;
		if (source.length == 0)
			return new byte[0];
		if (begin + 1 > source.length)
			throw new IllegalArgumentException("begin position out of range: " + begin);
		int length = source.length - begin;
		byte[] sub = new byte[length];
		System.arraycopy(source, begin, sub, 0, length);
		return sub;
	}

	public static byte[] sub(byte[] source, int begin, int length) {
		if (source == null)
			return null;
		if (source.length == 0)
			return new byte[0];
		if (begin + 1 > source.length)
			throw new IllegalArgumentException("begin position out of range: " + begin);
		if (begin + length > source.length)
			throw new IllegalArgumentException("length out of range: " + length);
		byte[] sub = new byte[length];
		System.arraycopy(source, begin, sub, 0, length);
		return sub;
	}
}
